<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AI VTuber - Live2D 渲染器</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
        
        body {
            background-color: #00FF00; /* 绿幕背景 */
            font-family: 'Microsoft YaHei', sans-serif;
        }
        
        #canvas {
            display: block;
            width: 100vw;
            height: 100vh;
        }
        
        #status {
            position: absolute;
            top: 10px;
            left: 10px;
            color: white;
            background: rgba(0, 0, 0, 0.7);
            padding: 10px 15px;
            border-radius: 5px;
            font-size: 14px;
            z-index: 1000;
        }
        
        #debug-info {
            position: absolute;
            top: 10px;
            right: 10px;
            color: white;
            background: rgba(0, 0, 0, 0.7);
            padding: 10px 15px;
            border-radius: 5px;
            font-size: 12px;
            font-family: monospace;
            z-index: 1000;
            max-width: 300px;
        }
        
        .status-ok { color: #00ff00; }
        .status-error { color: #ff0000; }
        .status-warning { color: #ffff00; }
    </style>
</head>
<body>
    <div id="status">正在加载...</div>
    <div id="debug-info"></div>
    <canvas id="canvas"></canvas>

    <!-- 使用国内 CDN 加载 PIXI.js 和 pixi-live2d-display -->
    <script src="https://unpkg.com/pixi.js@7.4.2/dist/pixi.min.js"></script>
    <script src="https://unpkg.com/pixi-live2d-display@0.5.0/dist/index.min.js"></script>
    
    <script>
        // 全局变量
        let app;
        let model;
        let ws;
        let reconnectTimer;
        const WS_URL = 'ws://localhost:8765';
        
        // 状态显示
        const statusEl = document.getElementById('status');
        const debugEl = document.getElementById('debug-info');
        
        function updateStatus(message, type = 'ok') {
            statusEl.innerHTML = `<span class="status-${type}">${message}</span>`;
            console.log(`[${type.toUpperCase()}] ${message}`);
        }
        
        function updateDebugInfo(info) {
            const lines = [
                `FPS: ${Math.round(app?.ticker?.FPS || 0)}`,
                `模型: ${model ? '已加载' : '未加载'}`,
                `WebSocket: ${ws?.readyState === 1 ? '已连接' : '未连接'}`,
                `嘴巴张度: ${info.mouthOpen || 0}`,
                `情感: ${info.emotion || 'neutral'}`,
                `头部角度X: ${info.angleX || 0}`,
                `头部角度Y: ${info.angleY || 0}`
            ];
            debugEl.innerHTML = lines.join('<br>');
        }
        
        // 初始化 PIXI 应用
        async function initApp() {
            updateStatus('初始化渲染引擎...', 'warning');
            
            app = new PIXI.Application({
                view: document.getElementById('canvas'),
                width: window.innerWidth,
                height: window.innerHeight,
                backgroundColor: 0x00FF00, // 绿幕
                backgroundAlpha: 1,
                antialias: true,
                autoDensity: true,
                resolution: window.devicePixelRatio || 1
            });
            
            // 窗口大小调整
            window.addEventListener('resize', () => {
                app.renderer.resize(window.innerWidth, window.innerHeight);
                if (model) {
                    model.x = window.innerWidth / 2;
                    model.y = window.innerHeight / 2;
                }
            });
            
            updateStatus('✓ 渲染引擎初始化完成', 'ok');
        }
        
        // 加载 Live2D 模型
        async function loadModel() {
            try {
                updateStatus('正在加载 Live2D 模型...', 'warning');
                
                // 模型路径（需要根据实际情况调整）
                const modelPath = './models/hiyori/runtime/hiyori_free_t08.model3.json';
                
                // 加载模型
                model = await PIXI.live2d.Live2DModel.from(modelPath);
                
                // 设置模型位置和缩放
                model.anchor.set(0.5, 0.5);
                model.x = window.innerWidth / 2;
                model.y = window.innerHeight / 2;
                
                // 根据窗口大小调整模型缩放
                const scale = Math.min(
                    window.innerWidth / model.width,
                    window.innerHeight / model.height
                ) * 0.8;
                model.scale.set(scale);
                
                // 添加到舞台
                app.stage.addChild(model);
                
                // 启用自动交互
                model.on('hit', (hitAreas) => {
                    if (hitAreas.includes('Body')) {
                        model.motion('Tap@Body');
                    }
                });
                
                updateStatus('✓ Live2D 模型加载成功', 'ok');
                console.log('模型信息:', model);
                
                // 启动动画循环
                startAnimation();
                
            } catch (error) {
                updateStatus(`✗ 模型加载失败: ${error.message}`, 'error');
                console.error('模型加载错误:', error);
            }
        }
        
        // 动画参数
        let currentParams = {
            mouthOpen: 0,
            emotion: 'neutral',
            angleX: 0,
            angleY: 0,
            eyeLOpen: 1,
            eyeROpen: 1
        };
        
        // 动画循环
        function startAnimation() {
            app.ticker.add(() => {
                if (!model) return;
                
                // 更新口型
                if (model.internalModel.coreModel) {
                    const mouthParam = model.internalModel.coreModel.getParameterIndex('ParamMouthOpenY');
                    if (mouthParam >= 0) {
                        model.internalModel.coreModel.setParameterValueByIndex(mouthParam, currentParams.mouthOpen);
                    }
                    
                    // 更新头部角度
                    const angleXParam = model.internalModel.coreModel.getParameterIndex('ParamAngleX');
                    if (angleXParam >= 0) {
                        model.internalModel.coreModel.setParameterValueByIndex(angleXParam, currentParams.angleX);
                    }
                    
                    const angleYParam = model.internalModel.coreModel.getParameterIndex('ParamAngleY');
                    if (angleYParam >= 0) {
                        model.internalModel.coreModel.setParameterValueByIndex(angleYParam, currentParams.angleY);
                    }
                    
                    // 更新眼睛
                    const eyeLParam = model.internalModel.coreModel.getParameterIndex('ParamEyeLOpen');
                    if (eyeLParam >= 0) {
                        model.internalModel.coreModel.setParameterValueByIndex(eyeLParam, currentParams.eyeLOpen);
                    }
                    
                    const eyeRParam = model.internalModel.coreModel.getParameterIndex('ParamEyeROpen');
                    if (eyeRParam >= 0) {
                        model.internalModel.coreModel.setParameterValueByIndex(eyeRParam, currentParams.eyeROpen);
                    }
                }
                
                // 更新调试信息
                updateDebugInfo(currentParams);
            });
        }
        
        // WebSocket 连接
        function connectWebSocket() {
            try {
                updateStatus('正在连接 WebSocket...', 'warning');
                
                ws = new WebSocket(WS_URL);
                
                ws.onopen = () => {
                    updateStatus('✓ WebSocket 已连接', 'ok');
                    clearTimeout(reconnectTimer);
                };
                
                ws.onmessage = (event) => {
                    try {
                        const data = JSON.parse(event.data);
                        
                        // 更新参数
                        if (data.type === 'update_params') {
                            currentParams = { ...currentParams, ...data.params };
                        }
                        
                        // 播放动作
                        if (data.type === 'play_motion' && model) {
                            const motionName = data.motion;
                            if (motionName) {
                                model.motion(motionName);
                            }
                        }
                        
                        // 设置表情
                        if (data.type === 'set_expression' && model) {
                            const expression = data.expression;
                            if (expression && model.expressions) {
                                model.expression(expression);
                            }
                        }
                        
                    } catch (error) {
                        console.error('消息解析错误:', error);
                    }
                };
                
                ws.onerror = (error) => {
                    updateStatus('✗ WebSocket 错误', 'error');
                    console.error('WebSocket 错误:', error);
                };
                
                ws.onclose = () => {
                    updateStatus('⚠ WebSocket 已断开，5秒后重连...', 'warning');
                    reconnectTimer = setTimeout(connectWebSocket, 5000);
                };
                
            } catch (error) {
                updateStatus(`✗ WebSocket 连接失败: ${error.message}`, 'error');
                reconnectTimer = setTimeout(connectWebSocket, 5000);
            }
        }
        
        // 初始化
        async function init() {
            try {
                await initApp();
                await loadModel();
                connectWebSocket();
            } catch (error) {
                updateStatus(`✗ 初始化失败: ${error.message}`, 'error');
                console.error('初始化错误:', error);
            }
        }
        
        // 启动
        window.addEventListener('load', init);
    </script>
</body>
</html>
